package org.twndmv.ejb;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.twndmv.bl.PersonMgmt;
import org.twndmv.blimpl.PersonMgmtImpl;
import org.twndmv.bo.Person;
import org.twndmv.dao.PersonDAO;
import org.twndmv.dao.VehicleRegistrationDAO;
import org.twndmv.dto.DTOUtils;
import org.twndmv.dto.PersonDTO;
import org.twndmv.dto.ResidenceDTO;
import org.twndmv.dto.VehicleRegistrationDTO;
import org.twndmv.jpa.PersonDAOImpl;
import org.twndmv.jpa.VehicleRegistrationDAOImpl;

@Stateless
public class PersonMgmtEJB implements PersonMgmtRemote {

	private static Log log = LogFactory.getLog(PersonMgmtEJB.class);

	@PersistenceContext(unitName = "dmvEntity")
	private EntityManager em;
	
	private PersonMgmt personManager;
	
	private VehicleRegistrationDAO vehicleDB;
	
	 @PostConstruct
	    public void init() {
	        try {
	            log.info("**** init ****");
	            log.info("em=" + em);
	            PersonDAO personDB = new PersonDAOImpl(em);
	            vehicleDB = new VehicleRegistrationDAOImpl(em);
	            personManager = new PersonMgmtImpl(personDB);
	        }
	        catch (Throwable ex) {
	            log.error("error in init", ex);
	            throw new EJBException("error in init" + ex);
	        }
	    }
	
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public List<PersonDTO> getPeopleByLastName(String name) {
		List<PersonDTO> results = new ArrayList<PersonDTO>();
		
		for(Person p : personManager.getPeopleByLastName(name)) {
			results.add(DTOUtils.convertPersonToDTO(p));
		}
		
		return results;
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public List<PersonDTO> getAllPeople() {
		List<PersonDTO> results = new ArrayList<PersonDTO>();
		
		for(Person p : personManager.getAllPeople()) {
			results.add(DTOUtils.convertPersonToDTO(p));
		}
		
		return results;
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public PersonDTO getPersonByID(long personId) {
		return DTOUtils.convertPersonToDTO(personManager.getPersonByID(personId));
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void updatePerson(PersonDTO oldPeep) {
		
		System.out.println("\n\n\n ID: " + oldPeep.getId());
		Person result = personManager.getPersonByID(oldPeep.getId());
		result.setFirstName(oldPeep.getFirstName());
		result.setLastName(oldPeep.getLastName());
		result.setCurrentResidence(DTOUtils.convertDTOToResidence(oldPeep.getCurrentResidence()));
		result.setNameSuffix(oldPeep.getNameSuffix());
		result.setMiddleName(oldPeep.getMiddleName());
		
		for(ResidenceDTO res : oldPeep.getResidences()) {
			result.getResidences().add(DTOUtils.convertDTOToResidence(res));
		}
		
		for(VehicleRegistrationDTO veh : oldPeep.getRegistrations()) {
			result.getRegistrations().add(vehicleDB.getRegistrationByID(veh.getId()));
		}
		
		result.setPhysicalDetails(DTOUtils.convertDTOToPhysicalDetails(oldPeep.getPhysicalDetails()));
		
		//personManager.updatePerson(DTOUtils.convertDTOToPerson(oldPeep));
		personManager.updatePerson(result);
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void createPerson(PersonDTO newPeep) {
		personManager.createPerson(DTOUtils.convertDTOToPerson(newPeep));
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void addList(List<PersonDTO> newPeeps) {
		for(PersonDTO newPeep : newPeeps) { 
			try  {
		  personManager.createPerson(DTOUtils.convertDTOToPerson(newPeep));
			} catch(Exception e) {
				log.error("Error adding list of people.  Transaction will be rolled back: " + e);
				em.getTransaction().rollback();
			}
		}
	}
}
